package com.tool.emulator.apple2;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.SourceDataLine;

/**
 * SpeakerUIImpl.java @author tl 2011-6-27
 */
public class SpeakerUIImpl implements SpeakerUI {
	public static final int SAMPLE_RATE = 88200;//44.1KHZ;
	public static final int RATE_FIX = 22;//1/4000
	public static final int BUFFER_SIZE = SAMPLE_RATE / 2;//0.5 second;
	public static final int HIGH_LEVEL = BUFFER_SIZE / 10 * 8;
	public static final int LOW_LEVEL = BUFFER_SIZE / 10 * 7;
	public static final AudioFormat FORMAT = new AudioFormat(SAMPLE_RATE, 8, 1, false, true);
	private final SourceDataLine line;
	private final byte[] buf = new byte[1024];
	private double base_time = 0;

	public SpeakerUIImpl() throws Exception {
		this.line = AudioSystem.getSourceDataLine(FORMAT);
		this.line.open(FORMAT, BUFFER_SIZE);
	}

	public void start() {
		this.line.start();
	}

	public void reset() {
		this.line.flush();
		this.base_time = 0;
	}

	public void stop() {
		this.line.stop();
	}

	//private int ct = 0;
	public void write(int val, double time) {
		int avail = line.available();
		/*
	    ct = (ct + 1)%500;
        if(ct == 0) System.err.println(line.available() + " low=" + LOW_LEVEL + ", high=" + HIGH_LEVEL);
        if(val > 255) 
            val = 255;
        if( val < 0)
            val = 0;*/
		int rate = SAMPLE_RATE;
		if (avail >= HIGH_LEVEL) rate += RATE_FIX;
		else if (avail < LOW_LEVEL) rate -= RATE_FIX;
		long count = (long) (base_time * rate);
		base_time += time;
		count = (long) (base_time * rate) - count;
		while (count > 0) {
			int c = (int) Math.min(count, buf.length);
			for (int i = 0; i < c; i++) buf[i] = (byte) val;
			this.line.write(buf, 0, c);
			count -= c;
		}

	}

}
